package com.sheep.demo.quartz.mange;

import com.sheep.demo.quartz.dto.CreateRemoteCronJobDTO;
import com.sheep.demo.quartz.dto.CreateRemoteJobDTO;
import com.sheep.demo.quartz.dto.RemoteJobParam;
import com.sheep.demo.quartz.scheduler.RemoteJob;
import jakarta.annotation.Resource;
import org.quartz.*;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class QuartzManager {
    @Resource
    private Scheduler scheduler;

    /**
     * 触发器 KEY
     */
    public TriggerKey getTriggerKey(String group, String name) {
        return TriggerKey.triggerKey(name, group);
    }

    /**
     * 定时任务 Key
     */
    public JobKey getJobKey(String group, String name) {
        return JobKey.jobKey(name, group);
    }

    /**
     * 获取表达式触发器
     */
    public CronTrigger getCronTrigger(String group, String name) {
        try {
            return (CronTrigger) this.scheduler.getTrigger(this.getTriggerKey(group, name));
        } catch (SchedulerException e) {
            throw new RuntimeException("getCronTrigger Fail", e);
        }
    }

    /**
     * 创建远程cron定时器
     */
    public void createRemoteCronJob(CreateRemoteCronJobDTO quartzJob) {
        try {
            // 构建任务
            JobDetail jobDetail = JobBuilder.newJob(RemoteJob.class)
                    .withIdentity(getJobKey(quartzJob.getGroup(), quartzJob.getName())).build();

            // 构建Cron调度器
            CronScheduleBuilder cronSchedule = CronScheduleBuilder
                    .cronSchedule(quartzJob.getCron())
                    //在处理定时任务（如Quartz框架中的任务）时，如果遇到触发器（Trigger）的触发时间被错过（即misfire），你可能需要指定当这种情况发生时应该如何处理。
                    //CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING 就是一种处理错过触发的指令，它的意思是当触发器错过其预定触发时间时，不采取任何操作，即忽略这次错过，继续按照正常的调度计划进行下一次触发。
                    .withMisfireHandlingInstructionDoNothing();
            // 任务触发器
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(quartzJob.getGroup(), quartzJob.getName()))
                    .startAt(quartzJob.getStartAt())
                    .endAt(quartzJob.getEndAt())
                    .withSchedule(cronSchedule).build();

            RemoteJobParam param = new CreateRemoteCronJobDTO();
            jobDetail.getJobDataMap().put("param", param);

            scheduler.scheduleJob(jobDetail, trigger);
            // 状态校验
            checkStop(quartzJob);
        } catch (SchedulerException e) {
            throw new RuntimeException("createJob Fail", e);
        }
    }

    /**
     * 校验停止定时器
     */
    public void checkStop(CreateRemoteJobDTO quartzJob) {
        try {
            //todo 盘点状态
//            if (quartzJob.getState() != JobState.JOB_RUN.getStatus()) {
            this.scheduler.pauseJob(getJobKey(quartzJob.getGroup(), quartzJob.getName()));
//            }
        } catch (SchedulerException e) {
            throw new RuntimeException("pauseJob Fail", e);
        }
    }
}
